package com.mybatis.pagesort;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class MyPageSortHelper {
    public static String removeSqlSemicolon(String sql) {
        final StringBuilder sqlBuilder = new StringBuilder(sql);
        if (sqlBuilder.lastIndexOf(";") == sqlBuilder.length() - 1) {
            sqlBuilder.deleteCharAt(sqlBuilder.length() - 1);
        }
        return sqlBuilder.toString();
    }
    //通过新的sql构建mappedstatement
    public static MappedStatement copyFromNewSql(MappedStatement ms, BoundSql boundSql,String sql)
    {
        BoundSql newBoundSql = copyFromBoundSql(ms, boundSql, sql);
        return copyFromBound(ms, new BoundSqlSqlSource(newBoundSql));

    }
    //通过新的boundsql构建新的mappedstatement，上面的方法调用这个方法
    private static MappedStatement copyFromBound(MappedStatement ms, BoundSqlSqlSource boundSqlSqlSource) {
        MappedStatement.Builder builder =
                new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), boundSqlSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
            StringBuilder keyProperties = new StringBuilder();
            for (String keyProperty : ms.getKeyProperties()) {
                keyProperties.append(keyProperty).append(",");
            }
            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
            builder.keyProperty(keyProperties.toString());
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.resultSetType(ms.getResultSetType());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }

    private static BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) {
        BoundSql newBoundSql = new BoundSql(ms.getConfiguration(),sql,boundSql.getParameterMappings(),
                boundSql.getParameterObject());
        for (ParameterMapping mapping : boundSql.getParameterMappings()) {
            String prop = mapping.getProperty();
            if (boundSql.hasAdditionalParameter(prop)) {
                newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));
            }
        }
        return newBoundSql;
    }


    //执行查询，这边有必要吗？只是将paramhandler和ps绑定在一起
    private static void setParameters(PreparedStatement countStmt, MappedStatement ms, BoundSql countBoundSql) throws SQLException {
        //configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);mybatis这样生成
        //点进去都一样，new DefaultParameterHandler 里面也获取了configuration
        ParameterHandler parameterHandler =
                new DefaultParameterHandler(ms, countBoundSql.getParameterObject(), countBoundSql);
        parameterHandler.setParameters(countStmt);
    }

    public static String getPageSql(String sql, int offset, int pageSize) {
        StringBuilder sqlBuilder = new StringBuilder(sql);

        if (offset <= 0) {
            return sqlBuilder.append(" limit ").append(pageSize).toString();
        }

        return sqlBuilder.append(" limit ").append(offset)
                .append(",").append(pageSize).toString();
    }

    private static class BoundSqlSqlSource implements SqlSource {
        BoundSql boundSql;

        public BoundSqlSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }
    }

    public static int queryTotal(String sql, MappedStatement ms, BoundSql boundSql) throws SQLException {
        Connection connection = null;
        PreparedStatement countStmt = null;
        ResultSet rs = null;
        try {
            connection = ms.getConfiguration().getEnvironment().getDataSource().getConnection();
            String countSql = "select count(0) from (" + sql + ") temp";
            countStmt = connection.prepareStatement(countSql);
            BoundSql countBoundSql = copyFromBoundSql(ms,boundSql,countSql);
            setParameters(countStmt, ms, countBoundSql);
            rs = countStmt.executeQuery();
            int total = 0;
            if (rs.next())
            {
                total = rs.getInt(1);
            }
            return total;
        } catch (SQLException e) {
            System.out.println("查询总记录数出错");
            throw e;
        }
        finally {
            if (rs != null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                }
            }
            if (countStmt != null) {
                try {
                    countStmt.close();
                } catch (SQLException e) {
                }
            }
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                }
            }
        }
    }

}
